import cv2 as cv
import numpy as np


def dilate(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    # cv.THRESH_BINARY_INV | cv.THRESH_OTSU的结果是像素值大于阈值则为0，小于阈值则为255。cv.THRESH_BINARY | cv.THRESH_OTSU则相反
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))  # 创建结构元素
    # 结构元素的形状
    # 结构元素的大小
    dst = cv.dilate(binary, kernel)  # 执行膨胀
    cv.imshow("dilate", dst)


def erode(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    dst = cv.erode(binary, kernel)
    cv.imshow("erode", dst)


def open(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    # 形态学操作
    # 第二个参数：要执行的形态学操作类型，这里是开操作
    binary = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)
    cv.imshow("open", binary)


def close(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    # 形态学操作
    # 第二个参数：要执行的形态学操作类型，这里是开操作
    binary = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel)
    cv.imshow("close", binary)


# 顶帽:原图像与开操作之间的差值图像,将突出比原轮廓亮的部分。
# 黑帽:闭操作图像与原图像的差值图像,将突出比原轮廓暗的部分。
def hat(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    dst = cv.morphologyEx(binary, cv.MORPH_TOPHAT, kernel)
    cv.imshow("topHat", dst)
    dst = cv.morphologyEx(binary, cv.MORPH_BLACKHAT, kernel)
    cv.imshow("BlackHat", dst)


# 形态学梯度
#     1、基本梯度：膨胀后的图像减去腐蚀后的图像得到的差值图像
def base(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    dst = cv.morphologyEx(binary, cv.MORPH_GRADIENT, kernel)
    cv.imshow("base", dst)


#     2、内部梯度：原图像减去腐蚀之后的图像得到的差值图像
#     3、外部梯度：图像膨胀之后减去原图像得到的差值图像
def i_e(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
    dm = cv.dilate(binary, kernel)
    em = cv.erode(binary, kernel)
    dst1 = cv.subtract(binary, em)
    dst2 = cv.subtract(dm, binary)
    cv.imshow("internal", dst1)
    cv.imshow("external", dst2)


src = cv.imread('imgs/test010.jpg')
cv.imshow("input_image", src)
dilate(src)
erode(src)
open(src)
close(src)
hat(src)
base(src)
i_e(src)
cv.waitKey(0)
cv.destroyAllWindows()
